package tcc.wa.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import tcc.wa.model.DailyWeatherForecast;
import tcc.wa.model.Location;
import tcc.wa.persistence.dao.DailyWeatherForecastDAO;
import android.content.Context;
import android.util.Log;

/**
 * Service class for DailyWeatherForecasts.
 */
public class DailyWeatherForecastService {
	
	private final String TAG = "DailyWeatherForecastService";
	
	private final String updateDailyWeatherForecastUrl = "http://api.wunderground.com/api/d09917472096c37e/forecast10day/q/{latitude},{longitude}.json";
	
	private final DailyWeatherForecastDAO dailyWeatherForecastDAO; 
	
	public DailyWeatherForecastService(Context context) {
		dailyWeatherForecastDAO = new DailyWeatherForecastDAO(context);
	}
	
	/**
	 * Updates the DailyWeatherForecasts.
	 *
	 * @param location the location
	 * @return a list containing the DailyWeatherForecasts for the next seven days
	 * @throws ClientProtocolException the client protocol exception
	 * @throws IOException Signals that an I/O exception has occurred
	 * @throws JSONException in case it fails to parse the server response
	 */
	public List<DailyWeatherForecast> update(Location location) throws ClientProtocolException, IOException, JSONException {
		Log.i(TAG, "Updating daily weather forecasts...");
		String requestString = updateDailyWeatherForecastUrl.replace("{latitude}", String.valueOf(location.getGeographicCoordinate().getLatitude()));
		requestString = requestString.replace("{longitude}", String.valueOf(location.getGeographicCoordinate().getLongitude()));
		HttpClient httpClient = new DefaultHttpClient();
		HttpGet request = new HttpGet(requestString);
		ResponseHandler<String> handler = new BasicResponseHandler();
		String result = httpClient.execute(request, handler);
		httpClient.getConnectionManager().shutdown();
		JSONObject jsonObject = new JSONObject(result);
		JSONArray forecastDays = jsonObject.getJSONObject("forecast").getJSONObject("simpleforecast").getJSONArray("forecastday");
		List<DailyWeatherForecast> dailyForecasts = buildDailyWeatherForecastsFrom(forecastDays, location);
		Log.i(TAG, "Successfully obtained new daily weather forecasts. Count: " + dailyForecasts.size());
		return dailyForecasts;
	}
	
	/**
	 * Saves a list of DailyWeatherForecasts.
	 *
	 * @param dailyForecasts the list of daily forecasts
	 */
	public void save(List<DailyWeatherForecast> dailyForecasts) {
		Log.i(TAG, "Saving current daily forecasts...");
		dailyWeatherForecastDAO.save(dailyForecasts);
		Log.i(TAG, "Successfully saved daily forecasts.");
	}
	
	/**
	 * Finds the last saved DailyWeatherForecasts.
	 *
	 * @return the last saved DailyWeatherForecasts
	 */
	public List<DailyWeatherForecast> findLast() {
		Log.i(TAG, "Finding last daily weather forecasts...");
		List<DailyWeatherForecast> dailyForecasts = dailyWeatherForecastDAO.findLast();
		if (dailyForecasts != null && dailyForecasts.size() > 0)
			Log.i(TAG, "Found last daily weather forecasts.");
		else
			Log.i(TAG, "Couldn't find last daily weather forecasts.");
		return dailyForecasts;
	}
	
	/**
	 * Builds the daily weather forecasts from the web service response.
	 *
	 * @param forecastDays a JSONObject containing the raw DailyWeatherForecasts
	 * @param location the device location
	 * @return a list containing the DailyWeatherForecasts for the next seven days
	 * @throws JSONException in case it fails to parse the server response
	 */
	private List<DailyWeatherForecast> buildDailyWeatherForecastsFrom(JSONArray forecastDays, Location location) throws JSONException {
		ArrayList<DailyWeatherForecast> forecasts = new ArrayList<DailyWeatherForecast>();
		int currentPeriod = 0;
		while (currentPeriod < 7) {
			JSONObject currentDay = forecastDays.getJSONObject(currentPeriod);
			DailyWeatherForecast forecast = new DailyWeatherForecast();
			Date date = new Date();
			date.setDate(currentDay.getJSONObject("date").getInt("day"));
			date.setMonth(currentDay.getJSONObject("date").getInt("month") - 1);
			date.setYear(currentDay.getJSONObject("date").getInt("year") - 1900);
			date.setHours(currentDay.getJSONObject("date").getInt("hour"));
			date.setMinutes(currentDay.getJSONObject("date").getInt("min"));
			date.setSeconds(currentDay.getJSONObject("date").getInt("sec"));
			double maximumTemperature = currentDay.getJSONObject("high").getDouble("celsius");
			double minimumTemperature = currentDay.getJSONObject("low").getDouble("celsius");
			double relativeHumidity = currentDay.getDouble("avehumidity");
			double precipitation = currentDay.getJSONObject("qpf_allday").getDouble("mm");
			forecast.setDate(date);
			forecast.setLocation(location);
			forecast.setMaximumTemperature(maximumTemperature);
			forecast.setMinimumTemperature(minimumTemperature);
			forecast.setRelativeHumidity(relativeHumidity);
			forecast.setPrecipitation(precipitation);
			forecasts.add(forecast);
			currentPeriod++;
		}
		return forecasts;
	}
}
